package crawl

import (
	"net/http"
)

type (
	RequestOption     interface{ Apply(req *http.Request) }
	RequestOptions    []RequestOption
	RequestOptionFunc func(req *http.Request)
)

func (opts RequestOptions) Apply(req *http.Request) {
	for _, opt := range opts {
		opt.Apply(req)
	}
}

func (fn RequestOptionFunc) Apply(req *http.Request) {
	if fn != nil {
		fn(req)
	}
}

func DefaultOption() RequestOption {
	return RequestOptions{
		HeaderSet("Accept", `text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9`),
		HeaderSet("Accept-Encoding", "gzip, deflate"),
		HeaderSet("Accept-Language", "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7"),
		HeaderSet("Connection", "keep-alive"),
		HeaderSet("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.56"),
	}
}

func Accept(accept string) RequestOption {
	if accept == "" {
		return HeaderDel("Accept")
	} else {
		return HeaderSet("Accept", accept)
	}
}

func AcceptEncoding(acceptEncoding string) RequestOption {
	if acceptEncoding == "" {
		return HeaderDel("Accept-Encoding")
	} else {
		return HeaderSet("Accept-Encoding", acceptEncoding)
	}
}

func AcceptLanguage(acceptLanguage string) RequestOption {
	if acceptLanguage == "" {
		return HeaderDel("Accept-Language")
	} else {
		return HeaderSet("Accept-Language", acceptLanguage)
	}
}

func Referer(referer string) RequestOption {
	if referer == "" {
		return HeaderDel("Referer")
	} else {
		return HeaderSet("Referer", referer)
	}
}

func UserAgent(userAgent string) RequestOption {
	if userAgent == "" {
		return HeaderDel("User-Agent")
	} else {
		return HeaderSet("User-Agent", userAgent)
	}
}

func ContentType(contentType string) RequestOption {
	if contentType == MimeNone {
		return HeaderDel("Content-Type")
	} else {
		return HeaderSet("Content-Type", contentType)
	}
}

func FormUrlencoded() RequestOption {
	return ContentType(MimeFormUrlencoded)
}

func KeepAlive(keepAlive ...bool) RequestOption {
	if len(keepAlive) == 0 || keepAlive[0] {
		return HeaderSet("Connection", "keep-alive")
	} else {
		return HeaderDel("Connection")
	}
}

func HeaderSet(key, value string) RequestOption {
	return RequestOptionFunc(func(req *http.Request) {
		req.Header.Set(key, value)
	})
}

func HeaderDel(keys ...string) RequestOption {
	return RequestOptionFunc(func(req *http.Request) {
		for _, key := range keys {
			req.Header.Del(key)
		}
	})
}
